﻿#include <graphics.h>
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>

#define WINDOW_WIDTH 400
#define WINDOW_HIGHT 400
#define CELL_SIZE 40
#define ROW_COUNT WINDOW_WIDTH / CELL_SIZE
#define COL_COUNT WINDOW_HIGHT / CELL_SIZE
#define FRAME_DURATION 1000 // 每帧的持续时间毫秒数

#define NO_INPUT

class Animal {
protected:
    std::string gender; // 性别
    int age; // 年龄
    int health; // 健康值
    int x, y; // 位置

    COLORREF color;

public:
    Animal(std::string gender, int age, int health, int x, int y, COLORREF color)
        : gender(gender), age(age), health(health), x(x), y(y), color(color) {
    }

    virtual ~Animal() {}

    std::string getGender() const { return gender; }
    int getAge() const { return age; }
    int getHealth() const { return health; }
    int getX() const { return x; }
    int getY() const { return y; }

    void setGender(const std::string& gender) { this->gender = gender; }
    void setAge(int age) { this->age = age; }
    void setHealth(int health) { this->health = health; }
    void setX(int x) { this->x = x; }
    void setY(int y) { this->y = y; }

    virtual void move() = 0; // 移动
    virtual void reproduce() = 0; // 繁殖
    virtual bool isDead() const = 0; // 是否死亡
    virtual void print() const = 0; // 输出信息
    virtual void eat(Animal& other) = 0; // 吃其他动物

	void draw() const {
        setfillcolor(color);
        //fillrectangle(x, y, x + CELL_SIZE, y + CELL_SIZE);
        fillrectangle(x * CELL_SIZE, y * CELL_SIZE, (x + 1) * CELL_SIZE, (y + 1) * CELL_SIZE);
    }

};

class Grass {
private:
    int x, y; // 位置
    int health; // 健康值

public:
    Grass(int x, int y, int health) : x(x), y(y), health(health) {}

    int getX() const { return x; }
    int getY() const { return y; }
    int getHealth() const { return health; }

    void beEaten() {
        // 被吃掉后健康值减少
        health -= 10;
    }

    void grow() {
        // 生长后健康值增加
        health = min(100, health + 10);
    }

    void print() const {
        // 输出草的信息
        std::cout << "草: 位置: (" << x << ", " << y << "), 健康值: " << health << std::endl;
    }

	void draw() const {
        setfillcolor(GREEN);
        //fillrectangle(x, y, x + CELL_SIZE, y + CELL_SIZE);
        fillrectangle(x * CELL_SIZE, y * CELL_SIZE, (x + 1) * CELL_SIZE, (y + 1) * CELL_SIZE);
    }

    void move() {}
};

// 羊类
class Sheep : public Animal {
public:
    Sheep(std::string gender, int age, int health, int x, int y)
        : Animal(gender, age, health, x, y, LIGHTGRAY) {
    }

    bool escape(Animal& other) {
        // 计算与捕食者的距离
        int distance = abs(x - other.getX()) + abs(y - other.getY());
        if (distance > 1) {
            std::cout << "羊 (" << x << ", " << y << ") 逃跑了" << std::endl;
            return true; // 逃跑了
        }
        else {
            std::cout << "羊 (" << x << ", " << y << ") 没有逃脱" << std::endl;
            return false; // 没有逃脱
        }
    }

    void eatGrass(Grass& grass) {
        // 吃草后健康值增加
        if (grass.getHealth() > 0) {
            int healthGain = grass.getHealth() / 2;
            setHealth(min(100, getHealth() + healthGain));
            grass.beEaten();
            std::cout << "羊 (" << x << ", " << y << ") 吃了草 (" << grass.getX() << ", " << grass.getY() << ")" << std::endl;
        }
    }

    void move() override {
        // 随机移动
        int oldX = x, oldY = y;
        int dx = rand() % 3 - 1;
        int dy = rand() % 3 - 1;

        // 放置出界
        x = max(0, min(ROW_COUNT - 1, x + dx));
        y = max(0, min(COL_COUNT - 1, y + dy));

        setHealth(max(0, getHealth() - 2)); // 每次移动消耗一定健康值
        std::cout << "羊 (" << oldX << ", " << oldY << ") 移动到 (" << x << ", " << y << ")" << std::endl;
    }

    void reproduce() override {
        // 达到繁殖条件时繁殖
        if (getAge() >= 1 && getHealth() >= 70) {
            setHealth(getHealth() - 30);
            // 新生羊
            new Sheep(getGender(), 0, 70, getX(), getY());
            std::cout << "羊 (" << x << ", " << y << ") 繁殖了一只新羊" << std::endl;
        }
    }

    bool isDead() const override {
        // 判断是否死亡
        return getAge() >= 12 || getHealth() <= 0;
    }

    void print() const override {
        // 输出羊的信息
        std::cout << "羊: 性别: " << getGender() << ", 年龄: " << getAge() << ", 生命值: " << getHealth() << ", 位置: (" << getX() << ", " << getY() << ")" << std::endl;
    }

    void eat(Animal& other) override {
        // 羊不能吃其他动物
    }
};

class Wolf : public Animal {
public:
    Wolf(std::string gender, int age, int health, int x, int y)
        : Animal(gender, age, health, x, y, RED) {
    }

    void eat(Animal& other) override {
        // 狼吃羊后，狼的健康值增加
        if (dynamic_cast<Sheep*>(&other) && other.getHealth() > 0) {
            int healthGain = other.getHealth() / 2;
            setHealth(min(100, getHealth() + healthGain));

            // 羊被狼攻击后，健康值减少
            other.setHealth(max(0, other.getHealth() - 50));
            std::cout << "狼 (" << x << ", " << y << ") 吃了羊 (" << other.getX() << ", " << other.getY() << ")" << std::endl;
        }
    }

    void move() override {
        // 随机移动
        int oldX = x, oldY = y;
        int dx = rand() % 3 - 1;
        int dy = rand() % 3 - 1;

        // 放置出界
        x = max(0, min(ROW_COUNT - 1, x + dx));
        y = max(0, min(COL_COUNT - 1, y + dy));

        setHealth(max(0, getHealth() - 5)); // 每次移动消耗一定健康值
        std::cout << "狼 (" << oldX << ", " << oldY << ") 移动到 (" << x << ", " << y << ")" << std::endl;
    }

    void reproduce() override {
        // 达到繁殖条件时繁殖
        if (getAge() >= 2 && getHealth() >= 80) {
            setHealth(getHealth() - 40);
            // 新生狼
            new Wolf(getGender(), 0, 80, getX(), getY());
            std::cout << "狼 (" << x << ", " << y << ") 繁殖了一只新狼" << std::endl;
        }
    }

    bool isDead() const override {
        // 判断是否死亡
        return getAge() >= 10 || getHealth() <= 0;
    }

    void print() const override {
        // 输出狼的信息
        std::cout << "狼: 性别: " << getGender() << ", 年龄: " << getAge() << ", 生命值: " << getHealth() << ", 位置: (" << getX() << ", " << getY() << ")" << std::endl;
    }
};

// 草原类
class Grassland {
private:
    std::vector<Animal*> animals; // 动物列表
    std::vector<Grass*> grasses; // 草列表

public:
    void initialize(int numWolves, int numSheep, int numGrasses) {
        // 初始化草原上的动物和草
        srand(time(0));
        for (int i = 0; i < numWolves; ++i) {
            std::string gender = (rand() % 2 == 0) ? "雄性" : "雌性";
            int age = rand() % 5;
            int health = 80 + rand() % 20;
            int x = rand() % ROW_COUNT;
            int y = rand() % COL_COUNT;

            animals.push_back(new Wolf(gender, age, health, x, y));
        }

        for (int i = 0; i < numSheep; ++i) {
            std::string gender = (rand() % 2 == 0) ? "雄性" : "雌性";
            int age = rand() % 6;
            int health = 70 + rand() % 30;
            int x = rand() % ROW_COUNT;
            int y = rand() % COL_COUNT;

            animals.push_back(new Sheep(gender, age, health, x, y));
        }

        for (int i = 0; i < numGrasses; ++i) {
            int x = rand() % ROW_COUNT;
            int y = rand() % COL_COUNT;
            int health = 100;

            grasses.push_back(new Grass(x, y, health));
        }
    }

    void renew() const {
		setlinecolor(LIGHTGRAY);
		setfillcolor(WHITE);
		// 遍历棋盘的每一行和每一列
		for (int row = 0; row < ROW_COUNT; ++row) {
			for (int col = 0; col < COL_COUNT; ++col) {
				int left = col * CELL_SIZE;
				int top = row * CELL_SIZE;
				int right = left + CELL_SIZE;
				int bottom = top + CELL_SIZE;

				solidrectangle(left, top, right, bottom); // 填充矩形
				rectangle(left, top, right, bottom); // 绘制线条
			}
		}

    }

    void update() {
        for (auto& animal : animals) {
            if (animal->isDead()) {
				delete animal;
				animal = nullptr;
				continue;
            }
            else {
                animal->move();
                animal->reproduce();

                if (dynamic_cast<Wolf*>(animal)) {
                    Wolf* wolf = dynamic_cast<Wolf*>(animal);
                    for (auto& other : animals) {
                        if (dynamic_cast<Sheep*>(other) && !other->isDead()) {
                            Sheep* sheep = dynamic_cast<Sheep*>(other);
                            if (!sheep->escape(*wolf)) {
                                wolf->eat(*sheep);
                            }
                        }
                    }
                }
                else if (dynamic_cast<Sheep*>(animal)) {
                    Sheep* sheep = dynamic_cast<Sheep*>(animal);
                    for (auto& grass : grasses) {
                        if (abs(sheep->getX() - grass->getX()) <= 1 && abs(sheep->getY() - grass->getY()) <= 1) {
                            sheep->eatGrass(*grass);
                        }
                    }
                }
            }
        }

		// 清除死亡的动物
		animals.erase(std::remove_if(animals.begin(), animals.end(), [](Animal* a) { return a == nullptr; }), animals.end());

        for (auto& grass : grasses) {
            grass->grow();
        }
    }

    void draw() const {
        renew();
        for (const auto& grass : grasses) {
            grass->draw();
        }

        for (const auto& animal : animals) {
            animal->draw();
        }
    }

    void run(int time) {
        for (int t = 0; t < time; ++t) {
            std::cout << "时间: " << t << std::endl;

            cleardevice();
            update();
            draw();
            Sleep(FRAME_DURATION);
        }
    }

    void printStatus() const {
        // 输出当前草原状况
        std::cout << "当前草原状况:" << std::endl;
        for (const auto& animal : animals) {
            if (animal != nullptr) {
                animal->print();
            }
        }
        for (const auto& grass : grasses) {
            grass->print();
        }
    }

    ~Grassland() {
        // 释放所有动物对象
        for (auto& animal : animals) {
            delete animal;
        }
    }
};


struct start_params {
    int numWolves; 
    int numSheep;
    int numGrasses;
    int time;
} params;

void prompt()
{
    int numWolves, numSheep, numGrasses, time;

#ifndef NO_INPUT
	std::cout << "请输入大灰狼的数量: ";
	cin >> numWolves;
	std::cout << "请输入小绵羊的数量: ";
	cin >> numSheep;
	std::cout << "请输入草地的数量: ";
	cin >> numGrasses;
	std::cout << "请输入运行时间: ";
	cin >> time;

    params.numWolves = numWolves;
    params.numSheep = numSheep;
    params.numGrasses = numGrasses;
    params.time = time; 
#else
    params.numWolves = 2; params.numSheep = 3; params.numGrasses = 2; params.time = 5;
#endif
}

int main() {
    prompt();
    // 初始化图形窗口
    initgraph(WINDOW_WIDTH, WINDOW_HIGHT);  // 像素窗口
    cleardevice();

    Grassland grassland;
    grassland.initialize(params.numWolves, params.numSheep, params.numGrasses);

    std::cout << "初始状态:" << std::endl;
    grassland.printStatus();

    grassland.run(params.time);

    std::cout << "最终状态:" << std::endl;
    grassland.printStatus();

    system("pause");
    closegraph();

    return 0;
}